﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace ASPMVCUtil.Helpers.Html.Grid
{
    public class GridBoundColumn<TModel, TValue>
    {
        public Expression<Func<TModel, TValue>> Expression { get; set; }
        public string Member { get; set; }
        public Func<TModel, TValue> Value { get; set; }

        public GridBoundColumn(Expression<Func<TModel, TValue>> expression)
        {
            IsNotNull(expression, "expression");

            Expression = expression;
            Member = MemberWithoutInstance(expression);
            Value = expression.Compile();
        }

        public static string MemberWithoutInstance(LambdaExpression expression)
        {
            MemberExpression memberExpression = ToMemberExpression(expression);

            if (memberExpression == null)
            {
                return null;
            }

            if (memberExpression.Expression.NodeType == ExpressionType.MemberAccess)
            {
                MemberExpression innerMemberExpression = (MemberExpression)memberExpression.Expression;

                while (innerMemberExpression.Expression.NodeType == ExpressionType.MemberAccess)
                {
                    innerMemberExpression = (MemberExpression)innerMemberExpression.Expression;
                }

                ParameterExpression parameterExpression = (ParameterExpression)innerMemberExpression.Expression;

                return memberExpression.ToString().Substring(parameterExpression.Name.ToString().Length + 1);
            }

            return memberExpression.Member.Name;
        }

        public static MemberExpression ToMemberExpression(LambdaExpression expression)
        {
            MemberExpression memberExpression = expression.Body as MemberExpression;

            if (memberExpression == null)
            {
                UnaryExpression unaryExpression = expression.Body as UnaryExpression;

                if (unaryExpression != null)
                {
                    memberExpression = unaryExpression.Operand as MemberExpression;
                }
            }

            return memberExpression;
        }

        public static void IsNotNull(object parameter, string parameterName)
        {
            if (parameter == null)
            {
                throw new ArgumentNullException(parameterName, parameterName + " can't be null");
            }
        }
    }
}
